#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <pthread.h>

#include "ncu_func.h"
#include "ncu_param.h"
#ifdef DMALLOC
#include <imp/dmalloc.h>
#endif
pthread_mutex_t mutex_ncu_ctrl = PTHREAD_MUTEX_INITIALIZER;

static ncu_param g_ncu_t30_param;
static ncu_params g_ncu_t30_params;

static int ncu_param_inited = 0;

extern void reg_ncu_write(uint32_t off, uint32_t value);
static int ncu_write_reg(uint32_t off, uint32_t reg)
{
	//printf("%s, off = 0x%x, reg = 0x%x\n", __func__, off, reg);
	reg_ncu_write(off, reg);
	return 0;
}

extern uint32_t reg_ncu_read(uint32_t off);
static uint32_t  ncu_read_reg(uint32_t off)
{
	uint32_t reg = 0;
	reg = reg_ncu_read(off);
	//printf("%s, off = 0x%x reg = 0x%x\n", __func__, off, reg);
	return reg;
}

static int ncu_lock()
{
	//printf("%s\n", __func__);
	return 0;
}

static int  ncu_unlock()
{
	//printf("%s\n", __func__);
	return 0;
}

static int ncu_ctrl_lock()
{
	pthread_mutex_lock(&mutex_ncu_ctrl);
	return 0;
}

static int  ncu_ctrl_unlock()
{
	pthread_mutex_unlock(&mutex_ncu_ctrl);
	return 0;
}

static void *ncu_t30_get_param(void)
{
	return &g_ncu_t30_param;
}

int ncu_ctrl_init()
{
	//ret = nuc_load_param("nd.bin");
	//ret = nuc_set_param(ncu);
	ncu_func_init_param initp = {
		.lock = ncu_lock,
		.unlock = ncu_unlock,
		.write_reg = ncu_write_reg,
		.read_reg = ncu_read_reg,
		.get_params = ncu_t30_get_param,
	};
	ncu_func_init(&initp);
	return 0;

}

int ncu_ctrl_bypass(int en)
{
	ncu_func_bypass(1);
	return 0;
}

int ncu_set_params(ncu_params *nps)
{
	ncu_ctrl_lock();
	memcpy(&g_ncu_t30_params, nps, sizeof(ncu_params));
	ncu_ctrl_unlock();
	return 0;
}

int ncu_ctrl_update(uint32_t gain)
{
	ncu_ctrl_lock();
	if (!ncu_param_inited) {
		printf("warn: ncu param do not inited\n");
		goto done;
	}
	//manual
	if (g_ncu_t30_param.NCU_CTRL_FLAGS&0x1) {
		goto done;
	}
	ncu_func_update(gain);
	ncu_ctrl_unlock();

	return 0;
done:
	ncu_ctrl_unlock();
	return 0;
}

static int ncu_mode = 0;

int ncu_ctrl_update_param(void)
{
	ncu_ctrl_lock();
	if (!ncu_mode) {
		memcpy(&g_ncu_t30_param, &g_ncu_t30_params.day, sizeof(ncu_param));
	} else {
		memcpy(&g_ncu_t30_param, &g_ncu_t30_params.night, sizeof(ncu_param));
	}
	ncu_param_inited = 1;
#ifndef NCUTEST
	extern uint32_t isp_get_total_gain(void);
	ncu_func_update(isp_get_total_gain());
#endif
	ncu_ctrl_unlock();
	return 0;
}

int ncu_ctrl_update_mode(int mode)
{
	if (ncu_mode != mode) {
		ncu_mode = mode;
	}
	ncu_ctrl_update_param();
	return 0;
}

int ncu_ctrl_manual_update()
{
	ncu_ctrl_lock();
#ifndef NCUTEST
	extern uint32_t isp_get_total_gain(void);
	ncu_func_update(isp_get_total_gain());
#else
	ncu_func_update(0);
#endif
	ncu_ctrl_unlock();
	return 0;
}
